import React, { useCallback, useEffect } from "react";

// npm i --save-dev @types/three
import * as THREE from "three";
// 加载模型库
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
// 解压模型库
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

import styles from "./index.module.scss";

//  CSS2DRenderer 不会跟随放大缩小（dom点击）
//  CSS3DRenderer 跟随模型（dom点击）
//  CSS3DSprite 同 CSS2DRenderer，但是能放大缩小（射线点击）
// import {
//   CSS2DRenderer,
//   CSS2DObject,
// } from "three/examples/jsm/renderers/CSS2DRenderer.js";

import {
  CSS3DRenderer,
  CSS3DObject,
} from "three/examples/jsm/renderers/CSS3DRenderer.js";

import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";

// type InfoType = {
//   minDistance: number;
//   maxDistance: number;
//   position: number[];
//   scale: number[];
//   hot: { title: string; id: number; position: number[]; scale: number[] }[];
// };

// 传入的参数配置
const info = {
  // 最大能到放大到多少，数字越小越大
  minDistance: 1.4,
  // 最小能到缩小到多少，数字越小越大
  maxDistance: 5,
  // 模型的初始位置、大小
  position: [0, 0, 0],
  scale: [1, 1, 1],
  hot: [
    {
      title: "热点1",
      id: 1,
      position: [0.17, 0.1, 0.13],
      scale: [0.002, 0.002, 0.002],
    },
    {
      title: "热点2",
      id: 2,
      position: [-0.17, 0.1, -0.13],
      scale: [0.002, 0.002, 0.002],
    },
  ],
};

function A7three() {
  // 热点点击
  const hotClickFu = useCallback((id: number) => {
    console.log("id:", id);
  }, []);

  useEffect(() => {
    // 初始化场景
    const scene = new THREE.Scene();
    // 初始化相机
    const camera = new THREE.PerspectiveCamera(
      45,
      window.innerWidth / window.innerHeight,
      1,
      1000
    );
    // 相机位置
    camera.position.set(1, 1, 1);
    camera.updateProjectionMatrix();
    // 初始化渲染器
    const renderer = new THREE.WebGLRenderer({
      // 设置抗锯齿
      antialias: true,
    });
    renderer.setSize(window.innerWidth, window.innerHeight);

    // 设置背景透明
    renderer.setClearColor(0x000000, 0);

    document.querySelector("#threeBox")?.appendChild(renderer.domElement);

    // 添加二维标签
    const labelRenderer = new CSS3DRenderer();
    labelRenderer.setSize(window.innerWidth, window.innerHeight);
    labelRenderer.domElement.style.position = "absolute";
    labelRenderer.domElement.style.top = "0";

    //将css2d节点渲染到页面中
    document.querySelector("#threeBox")?.appendChild(labelRenderer.domElement);

    // 初始化控制器
    const controls = new OrbitControls(camera, labelRenderer.domElement);
    // 开启惯性
    controls.enableDamping = true;

    // controls.enableZoom = false;//禁止缩放  
    //最大能到放大到多少，数字越小越大
    controls.minDistance = info.minDistance;
    // 最小能到缩小到多少，数字越小越大
    controls.maxDistance = info.maxDistance;
    //是否开启右键拖拽
    controls.enablePan = false;

    // 控制缩放倍数
    controls.minZoom = 0.01;
    controls.maxZoom = 0.05;

    // 初始化loader
    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath("./draco/");

    dracoLoader.setDecoderConfig({ type: "js" });
    dracoLoader.preload();

    const gltfLoader = new GLTFLoader();
    gltfLoader.setDRACOLoader(dracoLoader);

    // const gui = new GUI();

    gltfLoader.load(
      "./model/bei.gltf",
      (gltf) => {
        const model = gltf.scene;
        // 模型的初始位置
        model.position.set(
          info.position[0],
          info.position[1],
          info.position[2]
        );
        model.scale.set(info.scale[0], info.scale[1], info.scale[2]);
        scene.add(model);

        // 添加二维标签
        // 创建标签 在init函数中

        info.hot.forEach((item) => {
          const div: HTMLElement = document.createElement("div");
          div.className = "label";
          div.innerHTML = `<img src="/model/icon_hotspot.png" alt="" />`;
          div.title = item.title;
          div.addEventListener("pointerdown", () => hotClickFu(item.id), false);
          // 创建css2d对象。用CSS2DObject包装HTML
          const divLabel = new CSS3DObject(div);
          // 设置2d对象的位置
          divLabel.position.set(
            item.position[0],
            item.position[1],
            item.position[2]
          );
          // 大小
          divLabel.scale.set(item.scale[0], item.scale[1], item.scale[2]);
          // 将2d对象添加到模型上
          scene.add(divLabel);

          // 自己调整位置
          // const tagFolder = gui.addFolder(item.title);
          // tagFolder.add(divLabel.position, "x", -200, 200).name("X Position"); // 调整标签x位置
          // tagFolder.add(divLabel.position, "y", -200, 200).name("Y Position"); // 调整标签y位置
          // tagFolder.add(divLabel.position, "z", -200, 200).name("Z Position"); // 调整标签z位置
          // tagFolder.open(); // 打开文件夹，默认显示控制器
        });
      },
      (progressEvent) => {
        // 加载进度条
        // const { loaded, total, lengthComputable } = progressEvent;
        // //lengthComputable  true 可以获取到当前文件的总字节大小
        // if (lengthComputable) {
        //   const progress = (loaded / total) * 100;
        //   console.log(progress + "% loaded");
        // } else {
        //   console.log("已加载" + loaded + "字节");
        // }
      }
    );

    // 添加平行光
    const light1 = new THREE.DirectionalLight(0xffffff, 1);
    light1.position.set(0, 10, 0);
    scene.add(light1);

    const light2 = new THREE.DirectionalLight(0xffffff, 1);
    light2.position.set(10, 0, 0);
    scene.add(light2);

    const light3 = new THREE.DirectionalLight(0xffffff, 1);
    light3.position.set(0, 0, 10);
    scene.add(light3);

    const light4 = new THREE.DirectionalLight(0xffffff, 1);
    light4.position.set(0, -10, 0);
    scene.add(light4);

    const light5 = new THREE.DirectionalLight(0xffffff, 1);
    light5.position.set(-10, 0, 0);
    scene.add(light5);

    const light6 = new THREE.DirectionalLight(0xffffff, 1);
    light6.position.set(0, 0, -10);
    scene.add(light6);

    // 渲染
    function render() {
      requestAnimationFrame(render);

      // 渲染二维标签
      labelRenderer.render(scene, camera);
      renderer.render(scene, camera);
      controls.update();
    }

    render();

    window.addEventListener(
      "resize",
      () => {
        labelRenderer.setSize(window.innerWidth, window.innerHeight);
        // 重置渲染器输出画布canvas尺寸
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 全屏情况下：设置观察范围长宽比aspect为窗口宽高比
        camera.aspect = window.innerWidth / window.innerHeight;
        // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
        // 但是不会每渲染一帧，就通过相机的属性计算投影矩阵(节约计算资源)
        // 如果相机的一些属性发生了变化，需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
        camera.updateProjectionMatrix();
      },
      true
    );
  }, [hotClickFu]);

  return <div id="threeBox" className={styles.A7three}></div>;
}

const MemoA7three = React.memo(A7three);

export default MemoA7three;
